package com.miniserver.servlet;

import java.io.IOException;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;

import com.miniserver.tql.TqlGlobal;
import com.miniserver.util.BussinessException;
import com.miniserver.util.LogUtil;

/**
 * Servlet implementation class DatabaseEngineServlet
 */
@WebServlet(name = "model", urlPatterns = "/d")
public class DatabaseEngineServlet extends HttpServlet {
	LogUtil log = LogUtil.getLogUtil("DatabaseEngineServlet");
	private static final long serialVersionUID = 1L;
	private static final String MODEL_NAME = "data";

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		try {
			this.handleRequest(request, response);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		try {
			this.handleRequest(request, response);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 执行post和get请求
	 * 
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	private void handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// long tick = System.currentTimeMillis();
		HashMap<String, String> values = new HashMap<String, String>();
		// 初始化value hash
		Enumeration<String> iter = request.getParameterNames();
		while (iter.hasMoreElements()) {
			String pName = iter.nextElement();
			String pValue = URLDecoder.decode(request.getParameter(pName), "UTF-8").replace("###", ".html");
			// String pValue = new
			// String(request.getParameter(pName).getBytes("ISO8859-1"),"UTF-8").replace("###",
			// ".html");
			values.put("?" + pName.toLowerCase(), pValue);
		}

		// 记录用户url
		this.userTrace(values, request);
		//
		if (!values.containsKey("?format")) {
			values.put("?format", "json");
		}

		String modelName = MODEL_NAME;
		String methodName = "";
		if (values.containsKey("?d")) {
			modelName = values.get("?d");
		}
		if (values.containsKey("?m")) {
			methodName = values.get("?m");
		}

		// 检测ip地址	
			String clintIp = request.getRemoteAddr();
			if (TqlGlobal.getIpModelWhiteMap().containsKey(modelName) && !TqlGlobal.getIpModelWhiteMap().get(modelName).contains(clintIp)) {
				throw new Exception();
			}
			if (TqlGlobal.getIpMethodWhiteMap().containsKey(modelName + "$$" + methodName)
					&& !TqlGlobal.getIpMethodWhiteMap().get(modelName + "$$" + methodName).contains(clintIp)) {
				throw new Exception();
			}		
		//
		String format = values.get("?format");
		if (format.equalsIgnoreCase("xml")) {
			this.outputXmlResponse(modelName, values, response);
		} else {
			this.outputJsonReponse(modelName, values, response);
		}
	}

	private void outputJsonReponse(String modelName, HashMap<String, String> values, HttpServletResponse response) throws IOException {
		String responseText = "";
		try {
			responseText = TqlGlobal.handleDatabaseRequest(modelName, values);
		} catch (BussinessException ex) {
			ex.printStackTrace();
			responseText = "{\"success\":false,\"code\":" + ex.getCode() + ",\"msg\":\"" + ex.getMessage() + "\"}";
		} catch (Exception e) {
			e.printStackTrace();
			log.error("outputJsonReponse", e);
			if (values.get("@error_message") != null) {
				responseText = (values.get("@error_message"));
			} else
				responseText = "{\"success\":false,\"code\":-1,\"msg\":\"服务器内部错误。\"}";
		}
		response.setCharacterEncoding("UTF-8");
		response.setHeader("Content-Type", "text/json");
		response.getWriter().append(responseText.toString());
	}

	private void outputXmlResponse(String modelName, HashMap<String, String> values, HttpServletResponse response) throws IOException {
		StringBuilder msg = new StringBuilder();
		try {
			String responseText = TqlGlobal.handleDatabaseRequest(modelName, values);
			if (StringUtils.isNotBlank(responseText)) {
				if (responseText.indexOf("<error_response>") > -1) {
					msg.append(responseText);
				} else {
					msg.append("<response>").append(responseText).append("</response>");
				}
			} else {
				msg.append("<response><code>1</code></response>");
			}
		} catch (BussinessException ex) {
			msg.append("<error_response><code>").append(ex.getCode()).append("</code><msg>");
			msg.append(ex.getMessage()).append("</msg></error_response>");
		} catch (Exception ex) {
			log.error("错误:" + ex.getMessage());
			if (values.get("@error_message") != null) {
				msg.setLength(0);
				msg.append(values.get("@error_message"));
			} else
				msg.append("<error_response><code>-1</code><msg>服务器内部错误</msg></error_response>");
		}
		//
		response.setCharacterEncoding("UTF-8");
		response.setHeader("Content-Type", "text/xml");
		response.getWriter().append(msg.toString());
	}

	private void userTrace(HashMap<String, String> values, HttpServletRequest request) {
		StringBuilder urlMsg = new StringBuilder();
		String hostVal = request.getHeader("host");
		if (StringUtils.isNotBlank(hostVal)) {
			urlMsg.append("host=").append(hostVal).append("$$");
		}
		String agentVal = request.getHeader("User-Agent");
		if (StringUtils.isNotBlank(agentVal)) {
			urlMsg.append("agent=").append(agentVal);
		}
		urlMsg.append("$$");
		Iterator<String> iterKey = values.keySet().iterator();
		while (iterKey.hasNext()) {
			String pName = iterKey.next();
			if (pName.startsWith("?") && pName.toLowerCase().indexOf("password") == -1 && pName.toLowerCase().indexOf("base64") == -1) {
				urlMsg.append(pName.toLowerCase()).append("=").append(values.get(pName)).append("$$");
			}
		}
		log.UserTrace(urlMsg.toString());
	}
}
